﻿/*
 * MessageReader.h
 */

#ifndef __GDK_MESSAGEREADER_H__
#define __GDK_MESSAGEREADER_H__


#include <gdk/core/Types.h>
#include <gdk/core/Exception.h>
#include <gdk/core/Callback.h>
#include <gdk/core/Stream.h>
#include <gdk/core/Message.h>
#include <gdk/core/Log.h>
#include <gdk/core/Property.h>
#include <gdk/core/CallStack.h>
#include <gdk/core/convert.h>



namespace gdk
{


	class GDK_CORE_EXPORT MessageParser
	{
	public:
		typedef gdk::CallbackHandler<void,gdk::Message*> CallbackHandler;
		typedef gdk::Unknown::Handle_T<gdk::Message>(*MessageCreator)(void);

	public:
		ClassId			_classId;
		MessageCreator	_messageCreator;
		CallbackHandler	_callback;

	public:
		MessageParser(void)
			:_messageCreator(NULL)
		{
		}

		MessageParser(MessageParser const &o)
			:_classId(o._classId)
			,_messageCreator(o._messageCreator)
			,_callback(o._callback)
		{
		}

		bool operator ==(MessageParser const& i) const
		{
			return	_classId==i._classId
				&&	_messageCreator==i._messageCreator
				&&	_callback==i._callback;
		}

		__INLINE__ bool operator !=(MessageParser const& i) const
		{
			return !(*this==i);
		}

		void parser(InputStream &is) const __THROW1
		{
			GDK_ASSERT( _messageCreator!=NULL );

			Message::Handle msg = _messageCreator();
			msg->importFrom(is);
			return _callback(msg);
		}

		template<typename TyMsg>
		MessageParser(void(*func)(TyMsg *))
			:_classId(TyMsg::getClassId_())
			,_messageCreator(&TyMsg::createMessage_)
			,_callback(func)
		{
		}
		template<typename TyClass,typename TyMsg>
		MessageParser(SharedPtr<TyClass> const &obj,void(TyClass::*func)(TyMsg *))
			:_classId(TyMsg::getClassId_())
			,_messageCreator(&TyMsg::createMessage_)
			,_callback(obj,func)
		{
		}
		template<typename TyClass,typename TyMsg>
		MessageParser(TyClass &obj,void(TyClass::*func)(TyMsg *))
			:_classId(TyMsg::getClassId_())
			,_messageCreator(&TyMsg::createMessage_)
			,_callback(obj,func)
		{
		}
		template<typename TyClass,typename TyMsg>
		MessageParser(TyClass *obj,void(TyClass::*func)(TyMsg *))
			:_classId(TyMsg::getClassId_())
			,_messageCreator(&TyMsg::createMessage_)
			,_callback(obj,func)
		{
		}
		template<typename TyClass,typename TyMsg>
		MessageParser(gdk::Unknown::Handle_T<TyClass> const &obj,void(TyClass::*func)(TyMsg *))
			:_classId(TyMsg::getClassId_())
			,_messageCreator(&TyMsg::createMessage_)
			,_callback(obj,func)
		{
		}
	};

	class GDK_CORE_EXPORT MessageReader
	{
	public:
		typedef MessageParser::CallbackHandler		CallbackHandler;
		typedef MessageParser::MessageCreator		MessageCreator;
		typedef std::map<ClassId,MessageParser>		MessageParserMap;
		typedef MessageParserMap::iterator			MessageParserMap_Iterator;
		typedef MessageParserMap::const_iterator	MessageParserMap_ConstIterator;

		class MessagePackage
		{
		public:
			const ClassId	_classId;
			InputStream&	_is;

		private:
			MessagePackage& operator =(const MessagePackage&)
			{
				GDK_ASSERT(false);
				return *this;
			}

		public:
			MessagePackage(const MessagePackage &o)
				:_classId(o._classId)
				,_is(o._is)
			{}
			MessagePackage(ClassId const& classId,InputStream& is)
				:_classId(classId)
				,_is(is)
			{}
		};
		typedef gdk::CallbackHandler<bool,const MessagePackage&>	MessagePackageHandler;

	private:
		MessageParserMap		_mapMsgParser;
		MessageParser			_nullMsgParser;
		MessagePackageHandler	_unknownPackageHandler;


	public:
		//-----------------------------------------------
		bool addMessageParser(MessageParser const &o)
		{
			GDK_ASSERT(o._messageCreator!=NULL);
			GDK_ASSERT(_mapMsgParser.find(o._classId)==_mapMsgParser.end());

			_mapMsgParser[o._classId]=o;

			return true;
		}
		template<typename TyMsg>
		bool addMessageParser(void(*func)(TyMsg *))
		{
			return addMessageParser(MessageParser(func));
		}
		template<typename TyClass,typename TyMsg>
		bool addMessageParser(SharedPtr<TyClass> const &obj,void(TyClass::*func)(TyMsg *))
		{
			return addMessageParser(MessageParser(obj,func));
		}
		template<typename TyClass,typename TyMsg>
		bool addMessageParser(TyClass &obj,void(TyClass::*func)(TyMsg *))
		{
			return addMessageParser(MessageParser(obj,func));
		}
		template<typename TyClass,typename TyMsg>
		bool addMessageParser(TyClass *obj,void(TyClass::*func)(TyMsg *))
		{
			return addMessageParser(MessageParser(obj,func));
		}
		template<typename TyClass,typename TyMsg>
		bool addMessageParser(gdk::Unknown::Handle_T<TyClass> const &obj,void(TyClass::*func)(TyMsg *))
		{
			return addMessageParser(MessageParser(obj,func));
		}
		//-----------------------------------------------
		void removeMessageParser(ClassId classId)
		{
			_mapMsgParser.erase(classId);
		}
		__INLINE__ void removeMessageParser(MessageParser const &o)
		{
			removeMessageParser(o._classId);
		}
		template<typename TyMsg>
		void removeMessageParser(void)
		{
			return removeMessageParser(TyMsg::getClassId_());
		}
		template<typename TyClass,typename TyMsg>
		void removeMessageParser(SharedPtr<TyClass> const &obj,void(TyClass::*func)(TyMsg *))
		{
			return removeMessageParser(MessageParser(obj,func));
		}
		template<typename TyClass,typename TyMsg>
		void removeMessageParser(TyClass &obj,void(TyClass::*func)(TyMsg *))
		{
			return removeMessageParser(MessageParser(obj,func));
		}
		template<typename TyClass,typename TyMsg>
		void removeMessageParser(TyClass *obj,void(TyClass::*func)(TyMsg *))
		{
			return removeMessageParser(MessageParser(obj,func));
		}
		template<typename TyClass,typename TyMsg>
		void removeMessageParser(gdk::Unknown::Handle_T<TyClass> const &obj,void(TyClass::*func)(TyMsg *))
		{
			return removeMessageParser(MessageParser(obj,func));
		}
		//-----------------------------------------------
		__INLINE__ MessageReader& operator +=(MessageParser const &o)
		{
			addMessageParser(o);
			return *this;
		}
		__INLINE__ MessageReader& operator -=(MessageParser const &o)
		{
			removeMessageParser(o);
			return *this;
		}
		//-----------------------------------------------
		void clearMessageParser(void)
		{
			_mapMsgParser.clear();
			_unknownPackageHandler.setNull();
		}
		//-----------------------------------------------
		static Message::Handle pop(InputStream &is);
		//-----------------------------------------------
		bool analyse(InputStream &is) __THROW1;
		//-----------------------------------------------
		bool analyse(const MessagePackage &pkg) __THROW1;
		//-----------------------------------------------
		__INLINE__ MessageParser const& getMessageParser(ClassId const &classId) const
		{
			MessageParserMap_ConstIterator it=_mapMsgParser.find(classId);
			if(it!=_mapMsgParser.end())
			{
				return it->second;
			}

			return _nullMsgParser;
		}

		__INLINE__ int getMessageParserCount(void) const
		{
			return (int)_mapMsgParser.size();
		}

		__INLINE__ void setUnknownPackageHandler(MessagePackageHandler const &packageHandler)
		{
			_unknownPackageHandler=packageHandler;
		}

		__INLINE__ MessagePackageHandler const& getUnknownPackageHandler(void) const
		{
			return _unknownPackageHandler;
		}

	};




}//namespace gdk


#endif //__GDK_MESSAGEREADER_H__
